﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Text;

namespace Office.Spreadsheet.UI
{
    class WorksheetViewModel : INotifyPropertyChanged
    {

        public int MinRow
        {
            get
            {
                if (Worksheet.BottomRightPane == null)
                    return 0;
                if (Worksheet.View.Pane == null)
                    return 0;
                if (Worksheet.View.Pane.State == PaneState.Split)
                    return 0;
                return Worksheet.TopLeftPane.Bottom + 1;

            }
        }
        public int MinColumn
        {
            get
            {
                if (Worksheet.BottomRightPane == null)
                    return 0;
                if (Worksheet.View.Pane == null)
                    return 0;
                if (Worksheet.View.Pane.State == PaneState.Split)
                    return 0;
                return Worksheet.TopLeftPane.Right + 1;

            }
        }
        public int MaxColumn
        {
            get
            {
                if (!IsFrozen)
                    return this.Worksheet.ScrollPane.MaxColumn;
                return Math.Max(this.Worksheet.ScrollPane.MaxColumn, MinColumn + 1);
            }
        }
        public int MaxRow
        {
            get
            {
                if (!IsFrozen)
                    return this.Worksheet.ScrollPane.MaxRow;
                return Math.Max( Worksheet.ScrollPane.MaxRow, MinRow + 1);

            }
        }
        bool IsFrozen
        {
            get
            {
                if (Worksheet.BottomRightPane == null)
                    return false;
                if (Worksheet.View.Pane == null)
                    return false;
                if (Worksheet.View.Pane.State == PaneState.Split)
                    return false;
                return true;
            }
        }
        private readonly Worksheet _worksheet;
        public Worksheet Worksheet { get { return _worksheet; } }

        public WorksheetViewModel(Worksheet worksheet)
        {
            Contract.Requires(worksheet != null);
            _worksheet = worksheet;
            WeakEventHelper.AddWeakPropertyChanged(_worksheet, OnWorksheetChanged);
            AddPane(worksheet.ScrollPane);
            if (_worksheet.View != null)
            {
                WeakEventHelper.AddWeakPropertyChanged(_worksheet.View, OnViewChanged);
                if (_worksheet.View.Pane != null)
                {
                    WeakEventHelper.AddWeakPropertyChanged(_worksheet.View, OnPaneChanged);
                }
            }

        }

        private void OnWorksheetPaneChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "MaxColumn":
                case "MinColumn":
                case "MinRow":
                case "MaxRow":
                    OnScrollChanged();
                    break;
            }
        }

        private void OnPaneChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "State")
            {
                OnScrollChanged();
            }
        }

        private void OnScrollChanged()
        {
            NotifyPropertyChanged("MaxRow");
            NotifyPropertyChanged("MaxColumn");
            NotifyPropertyChanged("MinRow");
            NotifyPropertyChanged("MinColumn");
        }

        private void OnViewChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Pane")
            {
                SheetView view = (SheetView)sender;
                if (view.Pane != null)
                    WeakEventHelper.AddWeakPropertyChanged(view.Pane, OnPaneChanged);
            }
        }
        void AddPane (WorksheetPane pane)
        {
            if (processed.Contains(pane))
                return;
            WeakEventHelper.AddWeakPropertyChanged(pane, OnWorksheetPaneChanged);
            processed.Add(pane);
        }

        private List<WorksheetPane> processed = new List<WorksheetPane>();
        private void OnWorksheetChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "View":
                    NotifyPropertyChanged("ScrollTop");
                    NotifyPropertyChanged("ScrollLeft");
                    {
                        if (Worksheet.View != null)
                            WeakEventHelper.AddWeakPropertyChanged(this.Worksheet.View, OnViewChanged);
                    }
                    break;
                case "ActiveCell"
                :
                case "Protection":
                    NotifyPropertyChanged("IsActiveCellFormulaVisible");
                    break;
                case "ScrollPane":
                    AddPane(Worksheet.ScrollPane);
                    NotifyPropertyChanged("ScrollTop");
                    NotifyPropertyChanged("ScrollLeft");
                    break;
            }
        }
        public bool IsActiveCellFormulaVisible
        {
            get
            {
                var cell = _worksheet.ActiveCell;
                if (!_worksheet.IsProtected)
                    return true;
                return cell == null || !cell.IsFormulaHidden;
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            Contract.Requires(GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null);
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }


    }
}
